package com.shop.admin.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.shop.admin.dao.ShopGoodsDao;
import com.shop.admin.dao.ShopOrderDao;
import com.shop.admin.entity.ShopGoods;
import com.shop.admin.entity.ShopIndent;
import com.shop.admin.entity.ShopOrder;
import com.shop.admin.service.ShopGoodsService;
import com.shop.admin.service.ShopIndentService;
import com.shop.admin.service.ShopOrderService;
import com.shop.admin.vo.RankingVo;
import lombok.SneakyThrows;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.stream.Collectors;

@Service
public class ShopGoodsServiceImpl extends ServiceImpl<ShopGoodsDao, ShopGoods> implements ShopGoodsService {

    @Autowired
    private ShopOrderService orderService;

    @Resource
    private ShopOrderDao shopOrderDao;

    @Autowired
    private ThreadPoolExecutor threadPoolExecutor;

    @Resource
    private ShopIndentService shopIndentService;


    @SneakyThrows
    @Override
    public List<RankingVo> ranking(Map<String, Object> params){
        List<ShopIndent> shopIndents = shopIndentService.list(new QueryWrapper<ShopIndent>().lambda().eq(ShopIndent::getOrgId, params.get("orgId")));
        List<Long> indentId = shopIndents.stream().map(i -> i.getIndentId()).collect(Collectors.toList());
        CompletableFuture<List<ShopGoods>> goodsListCompletableFuture = CompletableFuture.supplyAsync(() -> {
            List<ShopGoods> goodsList = this.list(new QueryWrapper<ShopGoods>()
                    .lambda().select(ShopGoods::getOrderId, ShopGoods::getOrderNum)
                    .in(ShopGoods::getIndentId,indentId)
            );
            if (CollectionUtils.isEmpty(goodsList)) {
                return Collections.emptyList();
            }
            return goodsList;
        }, threadPoolExecutor);

        List<ShopGoods> goodsList = goodsListCompletableFuture.get();

        CompletableFuture<Set<Integer>> orderIdSetsCompletableFuture = goodsListCompletableFuture.thenApplyAsync((res) -> {
            Set<Integer> orderIds = goodsList.parallelStream().map(ShopGoods::getOrderId).collect(Collectors.toSet());
            if (CollectionUtils.isEmpty(orderIds)) {
                return Collections.emptySet();
            }
            return orderIds;
        }, threadPoolExecutor);

        Set<Integer> orderIds = orderIdSetsCompletableFuture.get();

        CompletableFuture<List<ShopOrder>> shopOrdersCompletableFuture = orderIdSetsCompletableFuture.thenApplyAsync((res) -> {
            List<ShopOrder> shopOrders = orderService.list(new QueryWrapper<ShopOrder>().lambda()
                    .select(ShopOrder::getOrderId, ShopOrder::getOrderName)
                    .in(ShopOrder::getOrderId, orderIds)
            ).stream().collect(Collectors.toList());
            return shopOrders;
        }, threadPoolExecutor);

        List<ShopOrder> shopOrders = shopOrdersCompletableFuture.get();

        List<RankingVo> collect = shopOrders.parallelStream().map(order -> {
            CompletableFuture<RankingVo> rankingVoCompletableFuture = goodsListCompletableFuture.thenApplyAsync((res) -> {
                RankingVo rankingVo = new RankingVo();
                Integer numCount = 0;
                for (ShopGoods goods : goodsList) {
                    if (goods.getOrderId().equals(order.getOrderId().intValue())) {
                        rankingVo.setOrderName(order.getOrderName());
                        numCount += goods.getOrderNum();
                    }
                    rankingVo.setOrderNum(numCount);
                }
                return rankingVo;
            }, threadPoolExecutor);

            try {
                return rankingVoCompletableFuture.get();
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (ExecutionException e) {
                e.printStackTrace();
            }
            return new RankingVo();
        }).collect(Collectors.toList());
        collect.sort((t1,t2)-> t2.getOrderNum().compareTo(t1.getOrderNum()));
        CompletableFuture.allOf(goodsListCompletableFuture,orderIdSetsCompletableFuture,shopOrdersCompletableFuture);
        return collect.stream().limit(10).collect(Collectors.toList());
    }

    @Override
    public int deleteXss(List<Long> indentIds) {
        int delete = this.baseMapper.delete(new QueryWrapper<ShopGoods>().lambda().in(ShopGoods::getIndentId, indentIds));
        return delete;
    }

    @Override
    public List<RankingVo> rankingList(Map<String, Object> params) {
        List<ShopOrder> goodsList = shopOrderDao.rankingList(params);
        List<RankingVo> collect = goodsList.stream().map(i -> new RankingVo(i.getOrderName(), i.getSaleCount().intValue())).collect(Collectors.toList());
        return collect;
    }
}
